using System;
using System.Collections.Generic;
using System.Net;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;

namespace MatrixFramework.Shared.Application.Exceptions
{
    /// <summary>
    /// 统一错误处理器
    /// </summary>
    public class ErrorHandler : ITransientDependency
    {
        private readonly ILogger<ErrorHandler> _logger;
        private readonly DefaultExceptionToErrorInfoConverter _errorInfoConverter;

        public ErrorHandler(
            ILogger<ErrorHandler> logger)
        {
            _logger = logger;
            _errorInfoConverter = new DefaultExceptionToErrorInfoConverter();
        }

        /// <summary>
        /// 处理异常
        /// </summary>
        public ErrorInfo HandleException(Exception exception)
        {
            if (exception == null)
            {
                return CreateUnknownError();
            }

            // 记录异常
            LogException(exception);

            // 转换为错误信息
            var errorInfo = _errorInfoConverter.Convert(exception);

            // 标准化错误信息
            return StandardizeErrorInfo(errorInfo, exception);
        }

        /// <summary>
        /// 处理业务异常
        /// </summary>
        public ErrorInfo HandleBusinessException(BusinessException exception)
        {
            if (exception == null)
            {
                return CreateUnknownError();
            }

            _logger.LogWarning(exception, "业务异常: {Message}", exception.Message);

            return new ErrorInfo(exception.Code, exception.Message, exception.Details)
            {
                Data = exception.Data,
                ValidationErrors = exception.ValidationErrors
            };
        }

        /// <summary>
        /// 处理验证异常
        /// </summary>
        public ErrorInfo HandleValidationException(ValidationException exception)
        {
            if (exception == null)
            {
                return CreateUnknownError();
            }

            _logger.LogWarning("验证异常: {Message}", exception.Message);

            return new ErrorInfo("VALIDATION_ERROR", "数据验证失败")
            {
                Details = exception.Message,
                ValidationErrors = exception.Errors
            };
        }

        /// <summary>
        /// 处理授权异常
        /// </summary>
        public ErrorInfo HandleAuthorizationException(AuthorizationException exception)
        {
            if (exception == null)
            {
                return CreateUnknownError();
            }

            _logger.LogWarning(exception, "授权异常: {Message}", exception.Message);

            return new ErrorInfo("AUTHORIZATION_ERROR", "访问被拒绝")
            {
                Details = exception.Message,
                HttpStatusCode = HttpStatusCode.Forbidden
            };
        }

        /// <summary>
        /// 处理未找到异常
        /// </summary>
        public ErrorInfo HandleNotFoundException(NotFoundException exception)
        {
            if (exception == null)
            {
                return CreateUnknownError();
            }

            _logger.LogInformation("资源未找到: {Message}", exception.Message);

            return new ErrorInfo("NOT_FOUND", exception.Message)
            {
                HttpStatusCode = HttpStatusCode.NotFound,
                ResourceType = exception.ResourceType,
                ResourceId = exception.ResourceId
            };
        }

        /// <summary>
        /// 处理并发异常
        /// </summary>
        public ErrorInfo HandleConcurrencyException(ConcurrencyException exception)
        {
            if (exception == null)
            {
                return CreateUnknownError();
            }

            _logger.LogWarning(exception, "并发冲突: {Message}", exception.Message);

            return new ErrorInfo("CONCURRENCY_ERROR", "数据已被其他用户修改，请刷新后重试")
            {
                Details = exception.Message,
                HttpStatusCode = HttpStatusCode.Conflict,
                RetryAfter = TimeSpan.FromSeconds(3)
            };
        }

        /// <summary>
        /// 创建标准化的HTTP响应
        /// </summary>
        public ErrorResponse CreateErrorResponse(ErrorInfo errorInfo)
        {
            return new ErrorResponse
            {
                Error = new ErrorDetail
                {
                    Code = errorInfo.Code,
                    Message = errorInfo.Message,
                    Details = errorInfo.Details,
                    Timestamp = DateTime.UtcNow,
                    TraceId = System.Diagnostics.Activity.Current?.TraceId.ToString(),
                    ValidationErrors = errorInfo.ValidationErrors
                },
                StatusCode = (int)(errorInfo.HttpStatusCode ?? HttpStatusCode.InternalServerError),
                RequestId = System.Diagnostics.Activity.Current?.Id
            };
        }

        private void LogException(Exception exception)
        {
            switch (exception)
            {
                case ValidationException _:
                    _logger.LogWarning("验证异常: {Message}", exception.Message);
                    break;
                case AuthorizationException _:
                    _logger.LogWarning(exception, "授权异常: {Message}", exception.Message);
                    break;
                case NotFoundException _:
                    _logger.LogInformation("资源未找到: {Message}", exception.Message);
                    break;
                case ConcurrencyException _:
                    _logger.LogWarning(exception, "并发冲突: {Message}", exception.Message);
                    break;
                case BusinessException _:
                    _logger.LogWarning(exception, "业务异常: {Message}", exception.Message);
                    break;
                default:
                    _logger.LogError(exception, "系统异常: {Message}", exception.Message);
                    break;
            }
        }

        private ErrorInfo StandardizeErrorInfo(ErrorInfo errorInfo, Exception exception)
        {
            // 确保有错误代码
            if (string.IsNullOrEmpty(errorInfo.Code))
            {
                errorInfo.Code = "UNKNOWN_ERROR";
            }

            // 确保有错误消息
            if (string.IsNullOrEmpty(errorInfo.Message))
            {
                errorInfo.Message = "发生了未知错误，请联系管理员";
            }

            // 设置HTTP状态码
            if (errorInfo.HttpStatusCode == null)
            {
                errorInfo.HttpStatusCode = exception switch
                {
                    ArgumentException => HttpStatusCode.BadRequest,
                    UnauthorizedAccessException => HttpStatusCode.Unauthorized,
                    ValidationException => HttpStatusCode.BadRequest,
                    NotFoundException => HttpStatusCode.NotFound,
                    AuthorizationException => HttpStatusCode.Forbidden,
                    ConcurrencyException => HttpStatusCode.Conflict,
                    BusinessException => HttpStatusCode.BadRequest,
                    _ => HttpStatusCode.InternalServerError
                };
            }

            // 添加时间戳和跟踪ID
            if (errorInfo.Data == null)
            {
                errorInfo.Data = new Dictionary<string, object>();
            }

            errorInfo.Data["timestamp"] = DateTime.UtcNow;
            errorInfo.Data["traceId"] = System.Diagnostics.Activity.Current?.TraceId.ToString();

            return errorInfo;
        }

        private ErrorInfo CreateUnknownError()
        {
            return new ErrorInfo("UNKNOWN_ERROR", "发生了未知错误，请联系管理员")
            {
                HttpStatusCode = HttpStatusCode.InternalServerError
            };
        }
    }

    #region 自定义异常类

    /// <summary>
    /// 业务异常基类
    /// </summary>
    public class BusinessException : Exception
    {
        public string Code { get; }
        public string? Details { get; }
        public new Dictionary<string, object> Data { get; }
        public List<ValidationError>? ValidationErrors { get; set; }

        public BusinessException(string code, string message, string? details = null)
            : base(message)
        {
            Code = code;
            Details = details;
            Data = new Dictionary<string, object>();
        }

        public BusinessException(string code, string message, Exception innerException)
            : base(message, innerException)
        {
            Code = code;
            Data = new Dictionary<string, object>();
        }

        public BusinessException WithData(string key, object value)
        {
            Data[key] = value;
            return this;
        }

        public BusinessException WithValidationErrors(List<ValidationError> errors)
        {
            ValidationErrors = errors;
            return this;
        }
    }

    /// <summary>
    /// 验证异常
    /// </summary>
    public class ValidationException : BusinessException
    {
        public List<ValidationError> Errors { get; }

        public ValidationException(List<ValidationError> errors)
            : base("VALIDATION_ERROR", "数据验证失败")
        {
            Errors = errors;
            WithValidationErrors(errors);
        }

        public ValidationException(string field, string message)
            : this(new List<ValidationError> { new ValidationError(field, message) })
        {
        }

        public ValidationException(string message)
            : base("VALIDATION_ERROR", message)
        {
            Errors = new List<ValidationError>();
        }
    }

    /// <summary>
    /// 授权异常
    /// </summary>
    public class AuthorizationException : BusinessException
    {
        public string? RequiredPermission { get; }
        public string? Resource { get; }

        public AuthorizationException(string message, string? requiredPermission = null, string? resource = null)
            : base("AUTHORIZATION_ERROR", message)
        {
            RequiredPermission = requiredPermission;
            Resource = resource;
            WithData("requiredPermission", requiredPermission);
            WithData("resource", resource);
        }
    }

    /// <summary>
    /// 资源未找到异常
    /// </summary>
    public class NotFoundException : BusinessException
    {
        public string? ResourceType { get; }
        public string? ResourceId { get; }

        public NotFoundException(string resourceType, string resourceId)
            : base("NOT_FOUND", $"{resourceType} '{resourceId}' 不存在")
        {
            ResourceType = resourceType;
            ResourceId = resourceId;
            WithData("resourceType", resourceType);
            WithData("resourceId", resourceId);
        }

        public NotFoundException(string message)
            : base("NOT_FOUND", message)
        {
        }
    }

    /// <summary>
    /// 并发异常
    /// </summary>
    public class ConcurrencyException : BusinessException
    {
        public string? EntityType { get; }
        public string? EntityId { get; }
        public byte[]? RowVersion { get; }

        public ConcurrencyException(string entityType, string entityId, byte[]? rowVersion = null)
            : base("CONCURRENCY_ERROR", $"{entityType} 已被其他用户修改，请刷新后重试")
        {
            EntityType = entityType;
            EntityId = entityId;
            RowVersion = rowVersion;
            WithData("entityType", entityType);
            WithData("entityId", entityId);
        }

        public ConcurrencyException(string message)
            : base("CONCURRENCY_ERROR", message)
        {
        }
    }

    /// <summary>
    /// 操作异常
    /// </summary>
    public class OperationException : BusinessException
    {
        public string? Operation { get; }
        public object? Context { get; }

        public OperationException(string operation, string message, object? context = null)
            : base("OPERATION_ERROR", message)
        {
            Operation = operation;
            Context = context;
            WithData("operation", operation);
            WithData("context", context);
        }
    }

    /// <summary>
    /// 配置异常
    /// </summary>
    public class ConfigurationException : BusinessException
    {
        public string? ConfigurationKey { get; }

        public ConfigurationException(string configurationKey, string message)
            : base("CONFIGURATION_ERROR", message)
        {
            ConfigurationKey = configurationKey;
            WithData("configurationKey", configurationKey);
        }
    }

    #endregion

    #region 数据模型

    /// <summary>
    /// 错误信息
    /// </summary>
    public class ErrorInfo
    {
        public string Code { get; set; } = string.Empty;
        public string Message { get; set; } = string.Empty;
        public string? Details { get; set; }
        public HttpStatusCode? HttpStatusCode { get; set; }
        public Dictionary<string, object> Data { get; set; } = new();
        public List<ValidationError>? ValidationErrors { get; set; }
        public TimeSpan? RetryAfter { get; set; }
        public string? ResourceType { get; set; }
        public string? ResourceId { get; set; }
        public string? StackTrace { get; set; }
        public string? InnerException { get; set; }

        public ErrorInfo() { }

        public ErrorInfo(string code, string message)
        {
            Code = code;
            Message = message;
        }

        public ErrorInfo(string code, string message, string details)
        {
            Code = code;
            Message = message;
            Details = details;
        }
    }

    /// <summary>
    /// 验证错误
    /// </summary>
    public class ValidationError
    {
        public string Field { get; set; } = string.Empty;
        public string Message { get; set; } = string.Empty;
        public string? Code { get; set; }

        public ValidationError(string field, string message, string? code = null)
        {
            Field = field;
            Message = message;
            Code = code;
        }
    }

    /// <summary>
    /// 错误响应
    /// </summary>
    public class ErrorResponse
    {
        public ErrorDetail Error { get; set; } = new();
        public int StatusCode { get; set; }
        public string? RequestId { get; set; }
    }

    /// <summary>
    /// 错误详情
    /// </summary>
    public class ErrorDetail
    {
        public string Code { get; set; } = string.Empty;
        public string Message { get; set; } = string.Empty;
        public string? Details { get; set; }
        public DateTime Timestamp { get; set; }
        public string? TraceId { get; set; }
        public List<ValidationError>? ValidationErrors { get; set; }
        public string? StackTrace { get; set; }
        public string? InnerException { get; set; }
    }

    #endregion

    #region 扩展方法

    /// <summary>
    /// 异常处理扩展方法
    /// </summary>
    public static class ExceptionExtensions
    {
        /// <summary>
        /// 获取异常的根原因
        /// </summary>
        public static Exception GetRootCause(this Exception exception)
        {
            var current = exception;
            while (current.InnerException != null)
            {
                current = current.InnerException;
            }
            return current;
        }

        /// <summary>
        /// 判断是否为业务异常
        /// </summary>
        public static bool IsBusinessException(this Exception exception)
        {
            return exception is BusinessException ||
                   exception.GetType().Name.EndsWith("Exception") &&
                   !exception.GetType().Namespace?.StartsWith("System") == true;
        }

        /// <summary>
        /// 获取用户友好的错误消息
        /// </summary>
        public static string GetUserFriendlyMessage(this Exception exception)
        {
            return exception switch
            {
                ValidationException => "输入数据有误，请检查后重试",
                AuthorizationException => "您没有权限执行此操作",
                NotFoundException => "请求的资源不存在",
                ConcurrencyException => "数据已被修改，请刷新后重试",
                BusinessException businessException => businessException.Message,
                UnauthorizedAccessException => "您没有权限访问此资源",
                ArgumentException => "输入参数有误",
                InvalidOperationException => "操作无效，请检查后重试",
                TimeoutException => "操作超时，请稍后重试",
                _ => "系统繁忙，请稍后重试"
            };
        }

        /// <summary>
        /// 获取错误代码
        /// </summary>
        public static string GetErrorCode(this Exception exception)
        {
            return exception switch
            {
                ValidationException => "VALIDATION_ERROR",
                AuthorizationException => "AUTHORIZATION_ERROR",
                NotFoundException => "NOT_FOUND",
                ConcurrencyException => "CONCURRENCY_ERROR",
                BusinessException businessException => businessException.Code,
                ArgumentException => "INVALID_ARGUMENT",
                InvalidOperationException => "INVALID_OPERATION",
                TimeoutException => "TIMEOUT_ERROR",
                _ => "UNKNOWN_ERROR"
            };
        }
    }

    /// <summary>
    /// 自定义异常到错误信息转换器接口
    /// </summary>
    public interface IExceptionToErrorInfoConverter
    {
        ErrorInfo Convert(Exception exception);
    }

    /// <summary>
    /// 默认异常到错误信息转换器
    /// </summary>
    public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConverter
    {
        public ErrorInfo Convert(Exception exception)
        {
            if (exception == null)
            {
                return new ErrorInfo("UNKNOWN_ERROR", "未知错误");
            }

            return new ErrorInfo(exception.GetErrorCode(), exception.Message)
            {
                Details = exception.StackTrace
            };
        }
    }

    #endregion
}